package org.hamster.multidropbox.dropbox.service
{
	import flash.events.IOErrorEvent;
	import flash.net.FileReference;
	import flash.net.URLLoader;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	
	import org.hamster.common.puremvc.events.ParallelEvent;
	import org.hamster.common.puremvc.events.ParallelEventHandler;
	import org.hamster.dropbox.DropboxEvent;
	import org.hamster.dropbox.models.DropboxFile;
	import org.hamster.multidropbox.dropbox.event.DropboxMultiUploadEvent;
	import org.hamster.multidropbox.dropbox.service.vo.DropboxMultiUploadVO;
	import org.hamster.multidropbox.dropbox.vo.AppDropboxClient;
	import org.hamster.multidropbox.dropbox.vo.AppDropboxFile;
	import org.hamster.multidropbox.dropbox.vo.AppDropboxLinkFolderItemVO;
	import org.hamster.multidropbox.dropbox.vo.AppDropboxLinkFoldersVO;

	[Event(type="org.hamster.multidropbox.dropbox.event.DropboxMultiUploadEvent", name="fileUploadSuccess")]
	[Event(type="org.hamster.multidropbox.dropbox.event.DropboxMultiUploadEvent", name="fileUploadFailure")]
	public class DropboxMultiUploadService
	{
		private var folderName:String;
		private var clientList:ArrayCollection;
		private var fileRefList:ArrayCollection;
		private var dropboxLinkFoldersVO:AppDropboxLinkFoldersVO;
		
		public function DropboxMultiUploadService(
			folderName:String, clientList:ArrayCollection, fileRefList:ArrayCollection, 
			dropboxLinkFoldersVO:AppDropboxLinkFoldersVO)
		{
			this.folderName = folderName;
			this.clientList = clientList;
			this.fileRefList = fileRefList;
			this.dropboxLinkFoldersVO = dropboxLinkFoldersVO;
		}
		
		private var metadataParallelHandler:ParallelEventHandler;
		private var linkFolderItemList:ArrayCollection;
		private var linkFolderDropboxFileList:ArrayCollection;
		private var multiUploadList:ArrayCollection;
		
		public function uploadFile():void
		{
			linkFolderItemList = new ArrayCollection();
			var client:AppDropboxClient;
			for each (client in clientList) {
				for each (var linkFoldersItemVO:AppDropboxLinkFolderItemVO in dropboxLinkFoldersVO.itemList) {
					if (client.uid == linkFoldersItemVO.clientId) {
						linkFolderItemList.addItem(linkFoldersItemVO);
						break;
					}
				}
			}
			
			metadataParallelHandler = new ParallelEventHandler();
			linkFolderDropboxFileList = new ArrayCollection();
			for (var i:int = 0; i < linkFolderItemList.length; i++) {
				client = clientList[i];
				metadataParallelHandler.addChild(client, 
					[DropboxEvent.METADATA_RESULT, DropboxEvent.METADATA_RESULT_NOT_MODIFIED], 
					DropboxEvent.METADATA_FAULT);
				client.metadata(folderName, 0, "", false);
			}
			
			metadataParallelHandler.addEventListener(ParallelEvent.ITEM_SUCCESS, metadataItemSuccessHandler);
			metadataParallelHandler.addEventListener(ParallelEvent.ITEM_FAILURE, metadataItemFailureHandler);
			metadataParallelHandler.addEventListener(ParallelEvent.ALL_FINISHED, metadataAllFinishedHandler);
			metadataParallelHandler.addEventListener(ParallelEvent.ALL_FAILURE, metadataAllFailureHandler);
		}
		
		
		private function metadataItemSuccessHandler(event:ParallelEvent):void
		{
			var client:AppDropboxClient = event.relatedEvent.currentTarget as AppDropboxClient;
			var file:AppDropboxFile = new AppDropboxFile(client, DropboxEvent(event.relatedEvent).resultObject as DropboxFile);
			linkFolderDropboxFileList.addItem(file);
		}
		
		private function metadataItemFailureHandler(event:ParallelEvent):void
		{
			
		}
		
		private function metadataAllFinishedHandler(event:ParallelEvent):void
		{
			var leftFileList:ArrayCollection = new ArrayCollection();
			for each (var file:AppDropboxFile in this.linkFolderDropboxFileList) {
				var linkItemVO:AppDropboxLinkFolderItemVO;
				for each (var tempLinkItemVO:AppDropboxLinkFolderItemVO in linkFolderItemList) {
					if (tempLinkItemVO.clientId == file.client.uid) {
						linkItemVO = tempLinkItemVO;
						break;
					}
				}
				leftFileList.addItem(file);
			}
			
			multiUploadList = new ArrayCollection();
			var leftFileRefList:ArrayCollection = new ArrayCollection();
			leftFileRefList.addAll(fileRefList);
			while (leftFileRefList.length !=0 && leftFileList.length != 0) {
				file = AppDropboxFile(leftFileList.removeItemAt(0));
				var linkItem:AppDropboxLinkFolderItemVO;
				for each (var tempLinkItem:AppDropboxLinkFolderItemVO in this.linkFolderItemList) {
					if (tempLinkItem.clientId == file.client.uid) {
						linkItem = tempLinkItem;
					}
				}
				multiUploadList.addItem(createMultiUploadVO(file.client,
					linkItem, file, leftFileRefList));
			}
			// done
			uploadNextFile();
		}
		
		private function uploadNextFile():void
		{
			var multiUpload:DropboxMultiUploadVO;
			
			for each (var tempMultiUpload:DropboxMultiUploadVO in multiUploadList) {
				if (tempMultiUpload.fileRefList.length > 0) {
					multiUpload = tempMultiUpload;
					break;
				}
			}
			
			if (multiUpload == null) {
				Alert.show("Done");
				return;
			}
			
			var client:AppDropboxClient = multiUpload.client;
			var fileRef:FileReference = multiUpload.fileRefList.removeItemAt(0) as FileReference;
			client.putFile(multiUpload.folderName, fileRef.name, fileRef.data);
			
			client.addEventListener(DropboxEvent.PUT_FILE_RESULT, putFileResultHandler);
			client.addEventListener(DropboxEvent.PUT_FILE_FAULT,  putFileFaultHandler);
		}
		
		private function putFileResultHandler(event:DropboxEvent):void
		{
			var client:AppDropboxClient = event.currentTarget as AppDropboxClient;
			client.removeEventListener(DropboxEvent.PUT_FILE_RESULT, putFileResultHandler);
			client.removeEventListener(DropboxEvent.PUT_FILE_FAULT,  putFileFaultHandler);
			trace ("upload success, doing next");
			uploadNextFile();
		}
		
		private function putFileFaultHandler(event:DropboxEvent):void
		{
			var client:AppDropboxClient = event.currentTarget as AppDropboxClient;
			client.removeEventListener(DropboxEvent.PUT_FILE_RESULT, putFileResultHandler);
			client.removeEventListener(DropboxEvent.PUT_FILE_FAULT,  putFileFaultHandler);
			
			trace ("upload failure, the reason is : " + (event.relatedEvent as DropboxEvent).resultObject);
			uploadNextFile();
		}
		
		private function uploadAllFinishedHandler(event:ParallelEvent):void
		{
			
		}
		
		private function uploadAllFailureHandler(event:ParallelEvent):void
		{
			
		}
		
		public function createMultiUploadVO(client:AppDropboxClient,
											linkItem:AppDropboxLinkFolderItemVO,
											file:AppDropboxFile, 
											leftFileRefList:ArrayCollection):DropboxMultiUploadVO
		{
			var multiUploadVO:DropboxMultiUploadVO = new DropboxMultiUploadVO();
			multiUploadVO.client = client;
			multiUploadVO.file = file;
			multiUploadVO.folderName = this.folderName;
			var fileRefListCollection:ArrayCollection = new ArrayCollection();
			var sizeLeft:Number = linkItem.maxSize - file.bytes;
			for each (var fileRef:FileReference in leftFileRefList)  {
				if (sizeLeft - fileRef.size >= 0) {
					fileRefListCollection.addItem(fileRef);
					sizeLeft -= fileRef.size;
				}
			}
			multiUploadVO.fileRefList = fileRefListCollection;
			for each (fileRef in fileRefListCollection) {
				leftFileRefList.removeItemAt(leftFileRefList.getItemIndex(fileRef));
			}
			return multiUploadVO;
		}
		
		private function metadataAllFailureHandler(event:ParallelEvent):void
		{
			
		}
	}
}